package com.generator.view.controller;

import com.generator.GeneratorApplication;
import com.google.gson.Gson;
import com.generator.code.MybatisCodeGenerator;
import com.generator.common.MysqlUtil;
import com.generator.common.bean.*;
import com.generator.common.constant.BaseConstant;
import com.generator.common.util.ConfigReadUtil;
import com.generator.common.util.SingletonMap;
import com.generator.common.util.StringUtils;
import com.generator.view.bean.GeneratorConfig;
import com.generator.view.enums.FXMLPage;
import com.generator.view.util.AlertUtil;
import com.generator.view.util.CookieUtils;
import com.generator.view.util.IdGeneratorBySnowflake;
import com.generator.view.util.UiBaseUtils;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.control.*;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.MouseButton;
import javafx.stage.DirectoryChooser;
import lombok.Getter;
import lombok.Setter;
import org.apache.log4j.Logger;

import java.io.File;
import java.net.URL;
import java.util.List;
import java.util.Optional;
import java.util.ResourceBundle;

/**
 * code generator main controller
 *
 * @author
 * @create 2018-03-17 11:07
 **/
public class MainUIController implements Initializable {
    private static final Logger LOG = Logger.getLogger(MainUIController.class);

    @Getter
    @Setter
    private Parent parent;
    private Gson gson = new Gson();

    //base end

    @FXML
    private Label connectionLabel;
    @FXML
    private Label systemConfig;
    @FXML
    private Label configsLabel;

    @FXML
    private Label clearAllLabel;

    @FXML
    private Button usernameBtn;

    @FXML
    private Button loginOutBtn;

    @FXML
    private TextField dbTreeSearch;

    /**
     * 树形菜单
     */
    @FXML
    private TreeView<TableColumnBean> leftDBTree;
    private TreeItem<TableColumnBean> rootItem = new TreeItem<>();
    private LeftTreeNodeController treeCell;
    //树形菜单 end

    @FXML
    @Getter
    private TextField hideID;
    @FXML
    @Getter
    private TextField tableNameField;
    @FXML
    @Getter
    private TextField tableCommentField;

    @FXML
    @Getter
    private TextField usernameField;

    @FXML
    @Getter
    private TextField domainObjectNameField;
    @FXML
    private TextField projectFolderField;
    @FXML
    private TextField javaDirectory;
    @FXML
    private TextField xmlDirectory;
    @FXML
    private TextField functionTarget;
    @FXML
    private TextField daoName;
    @FXML
    private TextField mapperName;

    //输入框 end

    @FXML
    private CheckBox autoIncrementCheckBox;
//    @FXML
//    private CheckBox useActualColumnNameCheckbox;
    @FXML
    private CheckBox lombokCheckBox;
    @FXML
    private CheckBox controllerCheckBox;
    @FXML
    private CheckBox serviceCheckBox;
    @FXML
    private CheckBox serviceImplCheckBox;
    @FXML
    private CheckBox assistStaticCheckBox;
    @FXML
    private Button generateCodeBtn;
    @FXML
    private Button diyColumnBtn;


    @Override
    public void initialize(URL location, ResourceBundle resources) {
        //初始化顶部菜单按钮事件控制器
        new MenuBtnEventController(this, connectionLabel, systemConfig, configsLabel, clearAllLabel).init();
        this.initFunctionalControl();

        String cookie = CookieUtils.getCookie("username");
        LOG.info("cookie:" + cookie);
        if (!StringUtils.isEmpty(cookie)) {
            SystemConfigBean systemConfigBean = MysqlUtil.selectSystemConfig(cookie);
            if (systemConfigBean != null) {

                SingletonMap.getInstance().putValue("id", systemConfigBean.getId());
                SingletonMap.getInstance().putValue("username", systemConfigBean.getName());

                initLeftDBTree();
                loadSchemaTreeNode();

                usernameField.setText(systemConfigBean.getName());
                usernameField.setDisable(true);
                usernameBtn.setVisible(false);
            }
        }else {

//            loginOutBtn.setVisible(false);
        }

        usernameBtn.setOnMouseClicked(event -> {
            MouseButton button = event.getButton();
            if (button != MouseButton.PRIMARY) {
                return;
            }
            String username = usernameField.getText();
            LOG.info("usernameField:" + username);

            loadData(username);
            initLeftDBTree();
            loadSchemaTreeNode();
            usernameBtn.setVisible(false);

            usernameField.setDisable(true);
            loginOutBtn.setVisible(true);
        });

        loginOutBtn.setOnMouseClicked(event -> {
            MouseButton button = event.getButton();
            if (button != MouseButton.PRIMARY) {
                return;
            }
            usernameField.setDisable(false);
            usernameField.setText("");
            usernameBtn.setVisible(true);
            loginOutBtn.setVisible(false);

            SingletonMap.getInstance().deleteValue("id");
            SingletonMap.getInstance().deleteValue("username");
            CookieUtils.removeCookie("username");

            initLeftDBTree();
            loadSchemaTreeNode();
        });
    }

    private void loadData(String username) {
        SystemConfigBean systemConfigBean = MysqlUtil.selectSystemConfig(username);
        if (systemConfigBean == null) {
            systemConfigBean = new SystemConfigBean();
            systemConfigBean.setId(IdGeneratorBySnowflake.newInstance.nextId() + "");
            systemConfigBean.setName(username);
            MysqlUtil.saveSystemConfig(systemConfigBean);
        }
        SingletonMap.getInstance().putValue("id", systemConfigBean.getId());
        SingletonMap.getInstance().putValue("username", username);
        CookieUtils.setCookie("username", systemConfigBean.getName());
        LOG.info("systemConfigBean:" + CookieUtils.getCookie("username"));
    }

    /**
     * 定制列事件
     */
    @FXML
    public void openTableColumnCustomizationPage() {
        InputVerifyBean verifyBean = UiBaseUtils.inputIsEmpty(new TextInputControl[]{tableNameField, domainObjectNameField}, getParent());
        if (!verifyBean.isPass()) {
            AlertUtil.showInfoAlert(verifyBean.getMessage() + "不能为空");
            return;
        }
        SelectTableColumnController controller = (SelectTableColumnController) UiBaseUtils.openDialog(SelectTableColumnController.class, diyColumnBtn.getText(), FXMLPage.SELECT_TABLE_COLUMN, true);
        controller.setMainUIController(this);
        controller.initColumnListView();
    }

    /**
     * 初始化左侧控件
     */
    public void initLeftDBTree() {
        MultipleSelectionModel<TreeItem<TableColumnBean>> model = leftDBTree.getSelectionModel();
        model.setSelectionMode(SelectionMode.MULTIPLE);
        leftDBTree.setFocusTraversable(false);
        leftDBTree.setRoot(rootItem);
        leftDBTree.setShowRoot(false);
        leftDBTree.setSelectionModel(model);
        leftDBTree.setCellFactory((TreeView<TableColumnBean> tv) -> treeCell = new LeftTreeNodeController(leftDBTree, this));
        loadSchemaTreeNode();
        //表搜索
        dbTreeSearch.setOnKeyPressed(event -> {
            KeyCode code = event.getCode();
            if (code == KeyCode.ENTER) {
                final String text = dbTreeSearch.getText();
                ObservableList<TreeItem<TableColumnBean>> list = rootItem.getChildren();
                for (TreeItem item : list) {
                    if (item.isExpanded()) {
                        if (text == null || text.isEmpty()) {
                            treeCell.loadDbTableNode(item, null);
                            return;
                        } else {
                            treeCell.loadDbTableNode(item, text);
                        }
                    }
                }
            }
        });
    }

    /**
     * 选择项目所在目录 事件
     */
    @FXML
    public void chooseProjectFolder() {
        DirectoryChooser directoryChooser = new DirectoryChooser();
        File selectedFolder = directoryChooser.showDialog(GeneratorApplication.mainStage);
        if (selectedFolder != null) {
            projectFolderField.setText(selectedFolder.getAbsolutePath() + File.separator);
        }
    }

    /**
     * 生成代码事件
     */
    @FXML
    public void generateCode() {
        LOG.info("lock state =============");
        InputVerifyBean verifyBean = UiBaseUtils.inputIsEmpty(new TextInputControl[]{tableNameField, domainObjectNameField, projectFolderField, javaDirectory, functionTarget, daoName, mapperName}, getParent());
        if (!verifyBean.isPass()) {
            AlertUtil.showInfoAlert(verifyBean.getMessage() + "不能为空");
            return;
        }
        GeneratorConfig config = getGeneratorConfigFromUI();
        String tablename = config.getTableName();
        String tableComment = config.getTableComment();
        String[] table_ = tablename.split(";");
        String[] tableComment_ = tableComment.split(";");
        if (StringUtils.isEmpty(tableComment)) {
            AlertUtil.showInfoAlert("求求你写下表注释！");
            return;
        }
        if (table_.length != tableComment_.length) {
            AlertUtil.showErrorAlert("注释个数和表个数不符合 (以;为分隔符)");
            return;
        }
        String domin = config.getDomainObjectName();
        String[] domin_ = domin.split(";");
        if (table_.length != domin_.length) {
            AlertUtil.showErrorAlert("实体类个数和表个数不符合 (以;为分隔符)");
            return;
        }
        Boolean b = MysqlUtil.isExistSystemConfig(SingletonMap.getInstance().getValueByKey("username"));
        if (!b) {
            AlertUtil.showInfoAlert("请先进行初始配置", 2);
            UiBaseUtils.openDialog(SystemConfigController.class, systemConfig.getText(), FXMLPage.SYSTEM_CONFIG, false);
            return;
        }
        LOG.info("==========开始生成代码==========");

//        DatabaseBean databaseBean = dao.selectOneDbConnection(config.getDbInfoID());

        DatabaseBean databaseBean = MysqlUtil.selectOneDbConnection(config.getDbInfoID());
//开始生成mybatis 部分代码
        new MybatisCodeGenerator(config, databaseBean);
        AlertUtil.showInfoAlert("生成完成");
        LOG.info("==========退出生成代码==========");
        generateCodeBtn.setDisable(false);
    }

    /**
     * 保存配置事件
     */
    @FXML
    public void saveGeneratorConfig() {
        InputVerifyBean verifyBean = UiBaseUtils.inputIsEmpty(new TextInputControl[]{tableNameField, domainObjectNameField, projectFolderField, javaDirectory, functionTarget, daoName, mapperName}, getParent());
        if (!verifyBean.isPass()) {
            AlertUtil.showInfoAlert(verifyBean.getMessage() + "不能为空");
            return;
        }
        TextInputDialog dialog = new TextInputDialog("");
        dialog.setTitle("保存当前配置");
        dialog.setContentText("请输入配置名称");
        Optional<String> result = dialog.showAndWait();
        if (result.isPresent()) {
            String name = result.get();
            if (StringUtils.isEmpty(name)) {
                AlertUtil.showErrorAlert("名称不能为空");
                return;
            }
            LOG.info("config name:" + name);
            try {
                GeneratorConfig uiData = getGeneratorConfigFromUI().setName(name);
                String json = gson.toJson(uiData);
                GeneratorConfigBean generatorConfigBean = MysqlUtil.selectOneGeneratorConfig(name);
                if (generatorConfigBean == null) {
                    generatorConfigBean = new GeneratorConfigBean();
                    generatorConfigBean.setConfigId(SingletonMap.getInstance().getValueByKey("id"));
                    generatorConfigBean.setData(json);
                    generatorConfigBean.setName(name);
                    generatorConfigBean.setId(IdGeneratorBySnowflake.newInstance.nextId() + "");
                    MysqlUtil.saveGeneratorConfig(generatorConfigBean);
                } else {
                    generatorConfigBean.setData(json);
                    MysqlUtil.updateGeneratorConfig(generatorConfigBean);
                }
            } catch (Exception e) {
                e.printStackTrace();
                AlertUtil.showErrorAlert("保存配置失败");
            }
        }
    }

    /**
     * 加载数据库树节点
     */
    public void loadSchemaTreeNode() {
        TreeItem rootTreeItem = leftDBTree.getRoot();
        if (rootTreeItem != null) {
            rootTreeItem.getChildren().clear();
        }
        try {
            String id = SingletonMap.getInstance().getValueByKey("id");
            List<DatabaseBean> dbConfigs = MysqlUtil.selectAllDbConnection(id);
            for (DatabaseBean bean : dbConfigs) {
                TreeItem<TableColumnBean> treeItem = new TreeItem<>();
                TableColumnBean tableBean = new TableColumnBean();
                tableBean.setTableName(bean.getName());
                treeItem.setValue(tableBean);
                ImageView dbImage = new ImageView(BaseConstant.COMPUTER_ICON);
                dbImage.setFitHeight(16);
                dbImage.setFitWidth(16);
                dbImage.setUserData(bean);
                treeItem.setGraphic(dbImage);
                rootTreeItem.getChildren().add(treeItem);
            }
        } catch (Exception e) {
            LOG.error("connect db failed, reason: {}", e);
            AlertUtil.showErrorAlert(e.getMessage());
        }
    }

    public GeneratorConfig getGeneratorConfigFromUI() {
        GeneratorConfig generatorConfig = new GeneratorConfig();
        generatorConfig.setDbInfoID(hideID.getText());
        generatorConfig.setTableComment(tableCommentField.getText());
        generatorConfig.setProjectFolder(projectFolderField.getText());
        generatorConfig.setDaoName(daoName.getText().replace("*", ""));
        generatorConfig.setMapperName(mapperName.getText().replace("*", ""));
        generatorConfig.setTableName(tableNameField.getText());
        generatorConfig.setDomainObjectName(domainObjectNameField.getText());
        generatorConfig.setUseActualColumnName(false);
        generatorConfig.setAutoIncrement(autoIncrementCheckBox.isSelected());
        generatorConfig.setLombok(lombokCheckBox.isSelected());
        generatorConfig.setFunctionTarget(functionTarget.getText());
        generatorConfig.setJavaDirectory(javaDirectory.getText());
        generatorConfig.setXmlDirectory(xmlDirectory.getText());
        generatorConfig.setGeneratorController(controllerCheckBox.isSelected());
        generatorConfig.setGeneratorService(serviceCheckBox.isSelected());
        generatorConfig.setGeneratorServiceImpl(serviceImplCheckBox.isSelected());
        generatorConfig.setAssistStatic(assistStaticCheckBox.isSelected());
        return generatorConfig;
    }

    public void setGeneratorConfigIntoUI(GeneratorConfig generatorConfig) {
        hideID.setText(generatorConfig.getDbInfoID());
        tableCommentField.setText(generatorConfig.getTableComment());
        projectFolderField.setText(generatorConfig.getProjectFolder());
        String daoName = generatorConfig.getDaoName();
        if (!StringUtils.isEmpty(daoName)) {
            this.daoName.setText(daoName);
        }
        String mapperName = generatorConfig.getMapperName();
        if (!StringUtils.isEmpty(mapperName)) {
            this.mapperName.setText(mapperName);
        }
        functionTarget.setText(generatorConfig.getFunctionTarget());
        tableNameField.setText(generatorConfig.getTableName());
        domainObjectNameField.setText(generatorConfig.getDomainObjectName());
        String javaDirectory = generatorConfig.getJavaDirectory();
        if (!StringUtils.isEmpty(javaDirectory)) {
            this.javaDirectory.setText(javaDirectory);
        }
        xmlDirectory.setText(generatorConfig.getXmlDirectory());
        autoIncrementCheckBox.setSelected(generatorConfig.isAutoIncrement());
//        useActualColumnNameCheckbox.setSelected(generatorConfig.isUseActualColumnName());
        lombokCheckBox.setSelected(generatorConfig.isLombok());
        controllerCheckBox.setSelected(generatorConfig.isGeneratorController());
        serviceCheckBox.setSelected(generatorConfig.isGeneratorService());
        serviceImplCheckBox.setSelected(generatorConfig.isGeneratorServiceImpl());
        assistStaticCheckBox.setSelected(generatorConfig.isAssistStatic());
    }

    /**
     * 初始化功能控制
     */
    private void initFunctionalControl() {
        String ctrlEach = ConfigReadUtil.getYmlString("generate.template.controller.base");
        String serviceBase = ConfigReadUtil.getYmlString("generate.template.service.base");
        String serviceIBase = ConfigReadUtil.getYmlString("generate.template.service-impl.base");
        if (StringUtils.isEmpty(ctrlEach)) {
            controllerCheckBox.setDisable(true);
        }
        if (StringUtils.isEmptys(serviceBase)) {
            serviceCheckBox.setDisable(true);
        }
        if (StringUtils.isEmptys(serviceIBase)) {
            serviceImplCheckBox.setDisable(true);
        }

    }
}
